home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2005 March / Macworld CD March 2005 - Marathon Trilogy.iso / Shareware World / Text Processing / HexEdit Release.sit / HexEdit Release / Project / Source / Main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-10-30  |  22.6 KB  |  840 lines  |  [TEXT/CWIE]

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is Copyright 1993 Jim Bumgardner.
  13.  * 
  14.  * The Initial Developer of the Original Code is Jim Bumgardner
  15.  * Portions created by Lane Roathe (LR) are
  16.  * Copyright (C) Copyright © 1996-2002.
  17.  * All Rights Reserved.
  18.  *
  19.  * Modified: $Date: 2004/09/10 04:05:47 $
  20.  * Revision: $Id: Main.c,v 1.38 2004/09/10 04:05:47 raving Exp $
  21.  *
  22.  * Contributor(s):
  23.  *        Lane Roathe (LR)
  24.  *        Nick Shanks (NS)
  25.  *        Scott E. Lasley (SEL) 
  26.  *        Brian Bergstrand (BB) 
  27.  *        Eric Froemling (EF)
  28.  */
  29.  
  30. // 05/10/01 - GAB: MPW environment support
  31. #ifdef __MPW__
  32. #include "MPWIncludes.h"
  33. #endif
  34.  
  35. #ifdef __MWERKS__
  36.     #include <debugging.h>
  37. #else
  38.     //#include <FlatCarbon/Debugging.h>
  39.     //#include <CoreServices/CoreServices.h>
  40. #endif
  41.  
  42. #include "Main.h"
  43. #include "Menus.h"
  44. #include "Prefs.h"
  45. #include "Utility.h"
  46. #include "EditWindow.h"
  47. #include "EditRoutines.h"
  48. #include "EditScrollbar.h"
  49. #include "HexCompare.h"
  50. #include "HexSearch.h"
  51.  
  52. // set up global & gPrefs structures here
  53. globals g;
  54. prefs_t gPrefs;
  55.  
  56. // LR: --- These are used to setup new UPP stuff ---
  57. AEEventHandlerUPP AEHandlerUPP, AECompareHandlerUPP;
  58.  
  59. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  60.     extern DlgHookUPP myGetFileUPP;
  61. #endif
  62.  
  63. extern WindowRef    CompWind1, CompWind2;
  64. static SInt32        caretTime;
  65. static Boolean        skipOpen = false;
  66.  
  67. #define kOpenFileAtLaunchDelay 3        //LR 187
  68. static UInt32        checkForOpen = 0;
  69.  
  70. // 05/10/01 - GAB: qd must be supplied by Interface.o applications
  71. #if !__MWERKS__ && !TARGET_API_MAC_CARBON
  72. QDGlobals    qd;
  73. #endif
  74.  
  75. // Do Idle Time Processing
  76.  
  77. /*** IDLE OBJECTS ***/
  78. static OSStatus _idleObjects( EventRecord *er )
  79. {
  80.     WindowRef theWin = FrontNonFloatingWindow();
  81.     ObjectWindowPtr objectWindow;
  82.  
  83.     while( theWin )
  84.     {
  85.         objectWindow = (ObjectWindowPtr)GetWRefCon( theWin );    //LR: 1.66 - don't use NULL window, and update for all windows!
  86.  
  87.         if( GetWindowKind( theWin ) == kHexEditWindowTag && objectWindow->Idle )
  88.             objectWindow->Idle( theWin, er );
  89.  
  90.         theWin = GetNextWindow( theWin );
  91.     }
  92.     return( noErr );
  93. }
  94.  
  95. // The Main Event Dispatcher - this routine should be called repeatedly
  96.  
  97. /*** HANDLE EVENT ***/
  98. OSStatus HandleEvent( void )
  99. {
  100.     EventRecord    theEvent;
  101.     Boolean        ok;
  102.  
  103.     // If the more modern WaitNextEvent is implemented, use it 
  104.  
  105. #if TARGET_API_MAC_CARBON    // LR: v1.6
  106.     ok = WaitNextEvent( everyEvent, &theEvent, caretTime, NULL );
  107. #else
  108.     if( g.WNEImplemented )
  109.         // We don't have to call SystemTask because WaitNextEvent calls it for us
  110.         // Get the next event ( LR 980716: give up lots of time, 'cos we don't need it : )
  111.         ok = WaitNextEvent( everyEvent, &theEvent, caretTime, NULL );
  112.     else
  113.     {
  114.         // we are running in ( Single ) Finder under system 6 or less
  115.         // Give Desk Accessories some processing time
  116.         SystemTask ();
  117.  
  118.         // Get the next event
  119.         ok = GetNextEvent( everyEvent, &theEvent );
  120.     }
  121. #endif
  122.  
  123.     if( IsDialogEvent( &theEvent ) )    DoModelessDialogEvent( &theEvent );
  124.     else if( ok )                        DoEvent( &theEvent );
  125.     else                                _idleObjects( &theEvent );
  126.  
  127.     //LR 187 -- apple events came in after the open app event, so we delay a while now.
  128.     if( checkForOpen )
  129.     {
  130.         if( !--checkForOpen && !skipOpen )
  131.             AskEditWindow( kWindowNormal );    // LR: -- voodoo can't have this
  132.     }
  133.  
  134.     return noErr;
  135. }
  136.  
  137.  
  138. /*** DO EVENT ***/
  139. OSStatus DoEvent( EventRecord *theEvent )
  140. {
  141.     short             windowCode;
  142.     WindowRef        theWin;
  143.     ObjectWindowPtr    objectWindow;
  144.     Rect            winRect;
  145.     long            windowKind;
  146.  
  147.     switch( theEvent->what )
  148.     {
  149.     case mouseDown:
  150.         // Find out where the mouse went down
  151.         windowCode = FindWindow ( theEvent->where, &theWin );
  152.  
  153.             switch ( windowCode )
  154.             {
  155. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  156.             case inSysWindow:
  157.                 SystemClick ( theEvent, theWin );
  158.                 break;
  159. #endif
  160.                 
  161.             case inMenuBar:
  162.                 AdjustMenus();
  163.                 HandleMenu( MenuSelect( theEvent->where ), theEvent->modifiers );
  164.                 break;
  165.  
  166.             default:            // Cursor was inside our theWin
  167.             {
  168.                 switch ( windowCode )
  169.                 {
  170.                     case inContent:    //EF 180 -- correctly handle selecting windows
  171.                     {
  172.                         // If the theWin isn't in the front
  173.                         if( theWin != FrontNonFloatingWindow() )
  174.                         {
  175.                             // Make it so...
  176.                             SelectWindow( theWin );
  177.                             AdjustMenus();
  178.                         }
  179.                         else    // Window is already in the front, handle the click
  180.                         {
  181.                             windowKind = GetWindowKind( theWin );
  182.                             objectWindow = (ObjectWindowPtr) GetWRefCon( theWin );
  183.  
  184.                             if( windowKind == kHexEditWindowTag && objectWindow->HandleClick )
  185.                                 objectWindow->HandleClick( theWin, theEvent->where, theEvent );
  186.                         }
  187.                         break;
  188.                     }
  189.  
  190.                     case inDrag:
  191.                     {
  192.                         Rect    dragRect;
  193. #if TARGET_API_MAC_CARBON    // LR: v1.6
  194.                         BitMap qdScreenBits;
  195.  
  196.                         GetQDGlobalsScreenBits( &qdScreenBits );
  197.                         dragRect = qdScreenBits.bounds;
  198. #else
  199.                         dragRect = qd.screenBits.bounds;    // LR: qd.
  200. #endif
  201.                         // Handle the dragging of the theWin
  202.                         DragWindow( theWin, theEvent->where, &dragRect );
  203.  
  204.                         break;
  205.                     }
  206.  
  207.                      case inGoAway:
  208.                         if( TrackGoAway( theWin, theEvent->where ) )
  209.                         {
  210.                             // If mouse is released inside the close box
  211.                             // Hide or close the theWin
  212.                             windowKind = GetWindowKind( theWin );
  213.                             if( windowKind == kHexEditWindowTag )
  214.                             {
  215.                                 CloseEditWindow( theWin );
  216.                             }
  217.                             else if( g.searchDlg && theWin == GetDialogWindow( g.searchDlg ) )        //LR: 1.7 -- compares also need GetDialogWindow!
  218.                             {
  219. // LR: v1.6.5                    DisposeDialog( g.searchDlg );
  220. // LR: v1.6.5                    g.searchDlg = NULL;
  221.  
  222.                                 HideWindow( GetDialogWindow( g.searchDlg ) );
  223.                             }
  224.                             else if( g.gotoDlg && theWin == GetDialogWindow( g.gotoDlg ) )        // LR: v1.6.5
  225.                             {
  226.                                 HideWindow( GetDialogWindow( g.gotoDlg ) );
  227.                             }
  228.  
  229.                             AdjustMenus();
  230.                         }
  231.                         break;
  232.  
  233.                     case inGrow:
  234.                     {
  235.                         long growResult;
  236.                         Rect r;
  237.  
  238.                         SelectWindow( theWin );
  239.                         SetRect( &r, kHexWindowWidth + 1, kHeaderHeight + (10 * kLineHeight), kHexWindowWidth + 1, g.maxHeight );
  240.  
  241.                         // Handle the mouse tracking for the resizing
  242.                         growResult = GrowWindow( theWin, theEvent->where, &r );
  243.  
  244.                         // Change the size of the theWin
  245.                         SizeWindow( theWin, LoWord( growResult ), HiWord( growResult ), true );
  246.  
  247.                         // LR: 1.7 - see if user wants sizing restricted to full lines
  248.                         GetWindowPortBounds( theWin, &r );
  249.                         if( gPrefs.constrainSize )
  250.                         {
  251.                             r.bottom = r.top + (short)((((r.bottom - r.top) / kLineHeight) - 1) * kLineHeight) + kHeaderHeight;    // force to full line heights
  252.                         }
  253.                         SizeWindow( theWin, (r.right - r.left - 1), (r.bottom - r.top), true ); //LR 190 -- don't grow window by 1 pixel
  254.  
  255.                         AdjustScrollBars( theWin, true );
  256. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  257. // LR: 1.5                    DrawPage( (EditWindowPtr) GetWRefCon( theWin ) );
  258. #endif
  259.  
  260.                         // Redraw the theWin
  261.                         SetPortWindowPort( theWin );
  262.                         InvalWindowRect( theWin, &r );
  263.                         break;
  264.                     }
  265.  
  266.                     case inZoomIn:
  267.                     case inZoomOut:
  268.                         if( TrackBox( theWin, theEvent->where, windowCode ) )
  269.                         {
  270.                             GetWindowPortBounds( theWin, &winRect );
  271.                             SetPortWindowPort( theWin );
  272.                             EraseRect( &winRect );
  273.  
  274.                             ZoomWindow( theWin, windowCode, true );
  275.                             AdjustScrollBars( theWin, true );
  276.  
  277.                             // Redraw the theWin
  278.                             GetWindowPortBounds( theWin, &winRect );
  279.                             SetPortWindowPort( theWin );
  280.                             InvalWindowRect( theWin, &winRect );
  281.                         }
  282.                 }
  283.             }
  284.             break;
  285.         }
  286.         break;
  287.         
  288.     // Was a key pressed?
  289.     case keyDown: 
  290.     case autoKey:
  291.         // Was the cmd-key being held down?    If so, process menu bar short cuts.
  292.         if( ( theEvent->modifiers & cmdKey ) != 0 )
  293.         {
  294.             AdjustMenus();
  295.             HandleMenu( MenuKey( (char) (theEvent->message & charCodeMask) ), theEvent->modifiers );
  296.         }
  297.         else
  298.         {
  299.             theWin = FrontNonFloatingWindow();    //LR: 1.66 don't use NULL window!
  300.             if( theWin )
  301.             {
  302.                 windowKind = GetWindowKind( theWin );
  303.                 objectWindow = (ObjectWindowPtr)GetWRefCon( theWin );
  304. // LR: v1.6.5 WHAT THE???            objectWindow->Dispose( theWin );
  305.                 if( windowKind == kHexEditWindowTag && objectWindow->ProcessKey != NULL )
  306.                     objectWindow->ProcessKey( theWin, theEvent );
  307.             }
  308.         }
  309.         break;
  310.  
  311.     // Does a theWin need to be redrawn?
  312.     case updateEvt:
  313.     {
  314.         theWin = (WindowRef) theEvent->message;
  315.  
  316.         objectWindow = (ObjectWindowPtr) GetWRefCon( theWin );
  317.         if( GetWindowKind( theWin ) == kHexEditWindowTag && objectWindow->Update )
  318.             objectWindow->Update( theWin );
  319.         break;
  320.     }
  321.  
  322.     // Has a theWin been activated or deactivated?
  323.     case activateEvt:
  324.         theWin = (WindowRef) theEvent->message;
  325.  
  326.         // Force it to be redrawn
  327.         objectWindow = (ObjectWindowPtr)GetWRefCon( theWin );
  328.         if( GetWindowKind( theWin ) == kHexEditWindowTag && objectWindow->Activate )
  329.         {
  330.             Boolean active = (theEvent->modifiers & activeFlag);
  331.             objectWindow->Activate( theWin, active );
  332.  
  333.             if( active && g.searchDlg )    //LR 1.72 -- if activating, get text from search dialog
  334.             {
  335.                 GetText( g.searchDlg, SearchTextItem, g.searchText );
  336.                 if( !StringToSearchBuffer( gPrefs.searchCase ) )
  337.                 {
  338.                     g.searchText[0] = g.searchBuffer[0] = 0;    //LR 1.73 -- on error, keep from repeating!
  339.                     SetText( g.searchDlg, SearchTextItem, g.searchText );
  340.                 }
  341.             }
  342.         }
  343.         break;
  344.  
  345.     case osEvt:
  346.         // Force it to be redrawn
  347.         switch ( theEvent->message >> 24 )
  348.         {
  349.             case suspendResumeMessage:
  350.                 theWin = FrontNonFloatingWindow();
  351.                 if( theWin )
  352.                 {
  353.                     objectWindow = (ObjectWindowPtr) GetWRefCon( theWin );
  354.                     windowKind = GetWindowKind( theWin );
  355.                     if( windowKind == kHexEditWindowTag && objectWindow->Activate )
  356.                         objectWindow->Activate( theWin, (theEvent->message & resumeFlag) > 0 );
  357.                 }
  358.                 if( theEvent->message & resumeFlag && ( CompWind1 && CompWind2 ) )
  359.                     DoComparison();
  360.                 break;
  361.         }
  362.         break;        
  363.  
  364.     case kHighLevelEvent:
  365. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  366.         if( g.sys7Flag )
  367. #endif
  368.             AEProcessAppleEvent( theEvent );
  369.         break;
  370.     }
  371.     return noErr;
  372. }
  373.  
  374. #pragma mark -
  375.  
  376. /*** GOT REQUIRED PARAMS ***/
  377. static Boolean _gotRequiredParams( const AppleEvent *theEvent )
  378. {
  379.     DescType returnedType;
  380.     Size     actualSize;
  381.     OSErr    err = AEGetAttributePtr( theEvent, keyMissedKeywordAttr, typeWildCard, &returnedType, NULL, 0, &actualSize );
  382.     return err == errAEDescNotFound;
  383. }
  384.  
  385. /*** DO OPEN EVENT ***/
  386. static OSStatus _doOpenAppleEvent( const AppleEvent *theEvent, Boolean print )
  387. {
  388.     OSStatus    error;
  389. //LR 175    Handle        docList = NULL;
  390.     FSSpec        myFSS;
  391.     AEDescList    theList;
  392.     AEKeyword    aeKeyword = keyDirectObject;
  393.     long        itemCount, i;
  394.     DescType    actualType;
  395.     Size        actualSize;
  396.     
  397.     // get event description
  398.     error = AEGetParamDesc( theEvent, keyDirectObject, typeAEList, &theList );
  399.     if( error != noErr )
  400.     {
  401. // 05/10/01 - GAB: DEBUGSTR not defined in non-Carbon builds
  402. #if !TARGET_API_MAC_CARBON
  403.         DEBUGSTR( "\pAEGetParamDesc" );
  404. #endif
  405.         return( error );
  406.     }
  407.  
  408.     // make sure event description is correct
  409.     if( !_gotRequiredParams( theEvent ) )
  410.     {
  411. // 05/10/01 - GAB: DEBUGSTR not defined for non-Carbon builds
  412. #if !TARGET_API_MAC_CARBON
  413.         DEBUGSTR( "\p_gotRequiredParams" );
  414. #endif
  415.         return( error );
  416.     }
  417.  
  418.     // count items to open
  419.     error = AECountItems( &theList, &itemCount );
  420.     if( error != noErr )
  421.     {
  422. // 05/10/01 - GAB: DEBUGSTR not defined for non-Carbon builds
  423. #if !TARGET_API_MAC_CARBON
  424.         DEBUGSTR( "\pAECountItems" );
  425. #endif
  426.         return( error );
  427.     }
  428.  
  429.     // open all items
  430.     for( i = 1; i <= itemCount; i++ )
  431.     {
  432.         error = AEGetNthPtr( &theList, i, typeFSS, &aeKeyword, &actualType, (Ptr) &myFSS, sizeof( FSSpec ), &actualSize );
  433.         if( error == noErr )
  434.         {
  435.             g.forkMode = FM_Smart;    //LR 190 -- open whichever fork we can find!
  436.             if( noErr == OpenEditWindow( &myFSS, kWindowNormal, !print ) )        //LR 181 -- show fork errors, etc. w/drag & drop open (but not print)
  437.             {
  438.                 if( print && kHexEditWindowTag == GetWindowKind( FrontNonFloatingWindow() ) )    // LR: 1.7 -- allow printing documents
  439.                 {
  440.                     PrintWindow( (EditWindowPtr)GetWRefCon( FrontNonFloatingWindow() ) );
  441.                     CloseEditWindow( FrontNonFloatingWindow() );
  442.                 }
  443.             }
  444.         }
  445.     }
  446.     AdjustMenus();    //LR: 1.7 -- show change in menus if required
  447.  
  448.     // event was handled successfully
  449.     AEDisposeDesc( &theList );
  450.     return noErr;
  451. }
  452.  
  453. /*** CORE EVENT HANDLER ***/
  454. static pascal OSErr _coreEventHandler( const AppleEvent *theEvent, AppleEvent *reply, long refCon )
  455. {
  456.     #pragma unused( reply, refCon )    // LR
  457.     DescType    actualType;
  458.     Size        actualSize;
  459.     DescType    eventID;
  460.     OSErr        error;
  461.  
  462.     error = AEGetAttributePtr(     ( AppleEvent* ) theEvent, keyEventIDAttr, typeType, &actualType, (Ptr) &eventID, sizeof( eventID ), &actualSize );
  463.     if( error )
  464.         return error;
  465.                                 
  466.     switch( eventID )
  467.     {
  468.         case kAEOpenApplication:
  469.             if( _gotRequiredParams( theEvent ) )
  470.             {
  471.                 checkForOpen = kOpenFileAtLaunchDelay;    // give us time before checking, to allow time to process AE
  472.             }
  473.             break;
  474.                 
  475.         case kAEOpenDocuments:
  476.             _doOpenAppleEvent( theEvent, false );
  477.             break;
  478.                 
  479.         case kAEPrintDocuments:
  480.             _doOpenAppleEvent( theEvent, true );
  481.             break;
  482.             
  483.         case kAEQuitApplication:
  484.             if( _gotRequiredParams( theEvent ) && CloseAllEditWindows())
  485.                 g.quitFlag = true;
  486.             break;
  487.     }
  488.     return noErr;
  489. }
  490.  
  491. #if (TARGET_API_MAC_CARBON)
  492. //EF 180 -- When we geta mouse wheel event move the croll position
  493. static pascal OSStatus _handleCarbonEvent(EventHandlerCallRef myHandler,EventRef theEvent, void* userData)
  494. {    
  495.     #pragma unused (myHandler,userData)
  496.     
  497.     switch (GetEventClass(theEvent))
  498.     {
  499.         case kEventClassMouse:
  500.         {
  501.             switch (GetEventKind(theEvent))
  502.             {
  503.                 case kEventMouseWheelMoved:
  504.                 {
  505.                     WindowPtr theWindow;
  506.                     long curPos,newPos;
  507.                     short windowCode;
  508.                     EditWindowPtr dWin;
  509.                     Point theMousePoint;
  510.                     long delta;
  511.                     GetEventParameter(theEvent,kEventParamMouseLocation,typeQDPoint,NULL,sizeof(theMousePoint),NULL,&theMousePoint);
  512.                     GetEventParameter(theEvent,kEventParamMouseWheelDelta,typeLongInteger,NULL,sizeof(delta),NULL,&delta);
  513.                     windowCode = FindWindow ( theMousePoint, &theWindow );
  514.                     if (windowCode == inContent)
  515.                     {
  516.                         if (GetWindowKind(theWindow) == kHexEditWindowTag)
  517.                         {
  518.                             dWin = (EditWindowPtr)GetWRefCon(theWindow);
  519.                             curPos = dWin->editOffset;
  520.                             newPos = curPos;
  521.                             newPos -= (kBytesPerLine * delta);
  522.                             ScrollToPosition( dWin, newPos );    
  523.                             return noErr;
  524.                         }
  525.                     }
  526.                     break;
  527.                 }
  528.                 
  529.             }
  530.         }
  531.     }
  532.     return eventNotHandledErr;
  533. }
  534. #endif //TARGET_API_MAC_CARBON
  535.  
  536. // LR --- handles only the VOODOO compare files AE
  537.  
  538. /*** COMPARE EVENT HANDLER ***/
  539. static pascal OSErr _compareEventHandler( const AppleEvent *theEvent, AppleEvent *reply, long refCon )
  540. {
  541.     #pragma unused( reply, refCon )            // LR
  542. //LR 177    extern WindowRef CompWind1, CompWind2;    // set in OpenEditWindow
  543.  
  544.     DescType    actualType;
  545.     Size        actualSize;
  546.     FSSpec    oldSpec, newSpec;
  547.     OSType    options;    // options are a text field, we get only the first 4 chars to make compares easy!
  548.     Boolean result;
  549.     OSErr        error;
  550.     
  551.  
  552.     skipOpen = true;
  553.  
  554.     // close previous file compare windows if open
  555.  
  556.     if( CompWind1 )    DisposeEditWindow( CompWind1 );
  557.     if( CompWind2 )    DisposeEditWindow( CompWind2 );
  558.     CompWind1 = CompWind2 = NULL;
  559.  
  560.     // Get the Compare suite events (file list and options)
  561.     error = AEGetParamPtr( theEvent, kAENewFileParam, typeFSS, &actualType, &newSpec, sizeof( newSpec ), &actualSize );
  562.     if( error ) return error;
  563.  
  564.     error = AEGetParamPtr( theEvent, kAEOldFileParam, typeFSS, &actualType, &oldSpec, sizeof( oldSpec ), &actualSize );
  565.     if( error ) return error;
  566.  
  567.     //LR 187 -- Options param is optional, and thus no error do we care about
  568.     error = AEGetParamPtr( theEvent, kAECompOptParam, typeChar, &actualType, &options, sizeof( options ), &actualSize );
  569.     if( !error )
  570.     {
  571.         if( 'rsrc' == options || 'RSRC' == options )
  572.             g.forkMode = FM_Rsrc;
  573.         else if( 'data' == options || 'DATA' == options )
  574.             g.forkMode = FM_Data;
  575.         else
  576.             g.forkMode = FM_Smart;        // default is "smart"
  577.     }
  578.  
  579.     error = OpenEditWindow( &newSpec, kWindowCompareTop, false );
  580.     if( !error )
  581.     {
  582.         error = OpenEditWindow( &oldSpec, kWindowCompareBtm, false );
  583.         if( !error )
  584.         {
  585. /* 185            if( gPrefs.searchType == CM_Match )
  586.                 result = PerformTextMatchCompare( (EditWindowPtr) GetWRefCon( CompWind1 ), (EditWindowPtr) GetWRefCon( CompWind2 ) );
  587.             else
  588.                 result = PerformTextDifferenceCompare( (EditWindowPtr) GetWRefCon( CompWind1 ), (EditWindowPtr) GetWRefCon( CompWind2 ) );
  589. */
  590.             //LR 187 -- always return success status if( result )
  591.             //LR 187 -- Check to make sure user didn't try to open the same file twice
  592.             if( CompWind1 && CompWind2 )
  593.             {
  594.                 result = PerformTextCompare( (EditWindowPtr) GetWRefCon( CompWind1 ), (EditWindowPtr) GetWRefCon( CompWind2 ) );
  595.  
  596.                 error = AEPutParamPtr( reply, keyDirectObject, typeBoolean, &result, sizeof( result ) );
  597.                 return error;
  598.             }
  599.             else
  600.                 error = dupFNErr;
  601.         }
  602.     }
  603.  
  604.     //LR 187 --  cleanup nice on error
  605.     if( CompWind1 )    DisposeEditWindow( CompWind1 );
  606.     if( CompWind2 )    DisposeEditWindow( CompWind2 );
  607.  
  608.     CompWind1 = CompWind2 = NULL;
  609.  
  610. //LR 187 -- no result on error!
  611. //    result = false;
  612. //    error = AEPutParamPtr( reply, keyDirectObject, typeBoolean, &result, sizeof( result ) );
  613.  
  614.     return error;
  615. }
  616.  
  617. /*** INIT APPLE EVENTS ***/
  618. static OSStatus _initAppleEvents( void )
  619. {
  620. #if !TARGET_API_MAC_CARBON    // LR: v1.7 (no need for seperate non-carbon code)
  621.     if( g.sys7Flag )
  622. #endif
  623.     {
  624.         AEHandlerUPP = NewAEEventHandlerUPP( _coreEventHandler );
  625. //LR: 1.7 -- Carbon requires specific handlers!        AEInstallEventHandler( kCoreEventClass, typeWildCard, AEHandlerUPP, 0, false );
  626.  
  627.         AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, AEHandlerUPP, 0, false );
  628.         AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, AEHandlerUPP, 0, false );
  629.         AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments, AEHandlerUPP, 0, false );
  630.         AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, AEHandlerUPP, 0, false );
  631.  
  632.         AECompareHandlerUPP = NewAEEventHandlerUPP( _compareEventHandler );
  633.         AEInstallEventHandler( kCompareEventClass, kAECompareEvent, AECompareHandlerUPP, 0, false );
  634.     }
  635.     return noErr;
  636. }
  637.  
  638. #if TARGET_API_MAC_CARBON
  639.  
  640. /*** INIT CARBON EVENTS ***/
  641. //EF 180 -- handle mouse wheen events via carbon
  642. static OSStatus _initCarbonEvents( void )
  643. {
  644.     long numTypes = 0;
  645.     OSErr err;
  646.     EventTypeSpec  eventType[15];
  647.     EventHandlerUPP theEventHandler = NewEventHandlerUPP(_handleCarbonEvent);
  648.     
  649.     /* specify which events we want to receive */
  650.     eventType[numTypes].eventClass = kEventClassMouse;
  651.     eventType[numTypes].eventKind = kEventMouseWheelMoved;
  652.     numTypes++;
  653.     err = InstallApplicationEventHandler(theEventHandler,numTypes,&eventType[0],NULL,NULL);
  654.     return err;
  655. }
  656. #endif
  657.  
  658. /*** CHECK ENVIRONMENT ***/
  659. static OSStatus _checkEnvironment( void )
  660. {
  661.     OSStatus    error;
  662.  
  663.     // get system version    // NS 1.7.1
  664.     error = Gestalt( gestaltSystemVersion, &g.systemVersion );        // this loads HIToolbox.framework on OS X
  665.  
  666. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  667.     if( !error )
  668.     {
  669.         SysEnvRec    sEnv;
  670.  
  671.         error = SysEnvirons( 1, &sEnv );
  672.         g.colorQDFlag = sEnv.hasColorQD;
  673.         g.sys7Flag = sEnv.systemVersion >= 0x0700;
  674.     }
  675. #endif
  676.  
  677.     return error;
  678. }
  679.  
  680. /*** INIT TOOLBOX ***/
  681. static OSStatus _initToolbox( void )
  682. {
  683. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  684.     MaxApplZone();
  685.     InitGraf( &qd.thePort );
  686.     InitFonts();
  687.     FlushEvents( everyEvent, 0 );
  688.     InitWindows();
  689.     InitMenus();
  690.     TEInit();
  691.     InitDialogs( 0L );
  692. #endif
  693.  
  694.     memset( &g, 0, sizeof(g) );    // make sure we have a known starting state!
  695.  
  696.     caretTime = (GetCaretTime()/3)*2;
  697.     return noErr;
  698. }
  699.  
  700. // Check if WaitNextEvent ( Multifinder ) is implemented on this Macintosh
  701. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  702. static OSStatus _initMultifinder( void )
  703. {
  704.     g.WNEImplemented = ( NGetTrapAddress(_WaitNextEvent, ToolTrap) != NGetTrapAddress(_Unimplemented, ToolTrap) );
  705.     return noErr;
  706. }
  707. #endif
  708.  
  709. /*** INIT GLOBALS ***/
  710. static OSStatus _initGlobals( void )
  711. {
  712.     // check for drag manager presence/attributes
  713.     SInt32 result = 0;
  714.     OSStatus error;
  715.  
  716.     error = Gestalt( gestaltDragMgrAttr, &result );
  717.     g.dragAvailable = (Boolean) (result & (1 << gestaltDragMgrPresent));
  718.     g.translucentDrag = (Boolean) (result & (1 << gestaltDragMgrHasImageSupport));
  719.     
  720.     // check appearance availablilty
  721.     // 05/10/01 - GAB: result is an int, not a pointer
  722.     result = 0;
  723.     error = Gestalt( gestaltAppearanceAttr, &result );
  724.     g.appearanceAvailable = (Boolean) (result & (1 << gestaltAppearanceExists));
  725.  
  726.     if( g.appearanceAvailable )
  727.     {
  728.         result = 0;
  729.         error = Gestalt( gestaltAppearanceVersion, &result );    //LR 181 -- only use appearance v1.1 or later!
  730.         g.useAppearance = (result >= 0x110);
  731.     }
  732.     else
  733.         g.useAppearance = false;
  734.  
  735.     if( g.useAppearance )
  736.         RegisterAppearanceClient();
  737.     
  738.     // check nav services availablilty
  739.     // 05/10/01 - GAB: MPW environment support
  740. #if !defined(__MC68K__) && !defined(__SC__)
  741.     g.navAvailable = (Boolean) NavServicesAvailable();
  742.     // BB: check for Navlib version, older versions were very buggy 
  743.     g.useNavServices = ((g.navAvailable) && (NavLibraryVersion() >= 0x0110));
  744.  
  745.     if( g.useNavServices )
  746.     {
  747.       if ( NavLoad() != noErr ) // BB: make sure NavLoad returns noErr
  748.         g.useNavServices = false;
  749.     }    
  750.  
  751.     // Startup InternetConfig (should only be done once!)
  752.     if( ICStart )
  753.     {
  754.         error = ICStart( &g.icRef, kAppCreator );            // start IC up
  755.         if( !error )
  756.         {
  757. #if !TARGET_API_MAC_CARBON
  758.             if( ICFindConfigFile )
  759.                 error = ICFindConfigFile( g.icRef, 0, NULL );    // configure IC
  760. #endif
  761.         }
  762.     }
  763. #endif
  764.  
  765.     // application global initalisation
  766.     g.forkMode = FM_Smart;
  767.     g.highChar = 0x7F;
  768.     g.watch = GetCursor( watchCursor );
  769.     g.iBeam = GetCursor( iBeamCursor );
  770.     g.searchBuffer[0] = g.searchText[0] = g.gotoText[0] = 0;
  771.     g.searchDisabled = false;
  772.     g.searchDlg = NULL;
  773.     g.gotoDlg = NULL;
  774.  
  775.     //LR: 1.66 - clear undo/redo records
  776.     memset( &gUndo, sizeof(UndoRecord), 0 );
  777.     memset( &gRedo, sizeof(UndoRecord), 0 );
  778.  
  779.     return( noErr );
  780. }
  781.  
  782. /*** MAIN ***/
  783. int main(int argc, char *argv[])    //LR 175
  784. {
  785. #pragma unused(argc,argv)
  786.     // Standard Mac Initialization
  787.     _initToolbox();
  788.  
  789. #if !TARGET_API_MAC_CARBON    // LR: v1.6
  790.     // Check if Multifinder ( WaitNextEvent ) is implemented
  791.     _initMultifinder();
  792. #endif
  793.  
  794.     // Check running environment
  795.     _checkEnvironment();
  796.  
  797.     _initGlobals();
  798.     _initAppleEvents();
  799.     InitMenubar();
  800.  
  801.     PrefsLoad();
  802.     InitializeEditor();
  803.     AdjustMenus();
  804.  
  805. #if TARGET_API_MAC_CARBON
  806.     _initCarbonEvents();    //EF 180 -- handle carbon events
  807. #else
  808.     if( !g.sys7Flag )
  809.         AskEditWindow( kWindowNormal );
  810. #endif
  811.  
  812.     InitCursor();    // NS: v1.6.6, moved here from _initToolbox()
  813.     
  814. #if TARGET_API_MAC_CARBON  // SEL: 1.7 - carbon session based printing
  815.     g.pageFormat = kPMNoPageFormat;
  816.     g.printSettings = kPMNoPrintSettings;
  817. #endif
  818.  
  819.     // main event loop
  820.     while( !g.quitFlag )
  821.         HandleEvent();
  822.  
  823.     CleanupEditor();
  824.  
  825. #if !defined(__MC68K__) && !defined(__SC__)        //LR 1.73 -- not available for 68K (won't even link!)
  826.     // BB: Unload NavServices
  827.     if( g.useNavServices )
  828.         NavUnload();
  829. #endif
  830.  
  831. // 05/10/01 - GAB: MPW environment support
  832. #if !defined(__MC68K__) && !defined(__SC__)
  833.     if( ICStop )
  834.     {
  835.         ICStop( g.icRef );    // shutdown IC
  836.     }
  837. #endif
  838.     return( 0 );
  839. }
  840.